package com.lightboat.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightboat.common.api.BaiDuJianKangApi;
import com.lightboat.common.constant.Constants;
import com.lightboat.common.constant.RedisConstants;
import com.lightboat.common.core.text.Convert;
import com.lightboat.common.enums.OperationTypeEnum;
import com.lightboat.common.enums.ProductType;
import com.lightboat.common.exception.ServiceException;
import com.lightboat.common.utils.DateUtils;
import com.lightboat.common.utils.RedisUtils;
import com.lightboat.common.utils.RegexpUtils;
import com.lightboat.system.domain.CrmProduct;
import com.lightboat.system.domain.CrmProductStockRecord;
import com.lightboat.system.domain.request.AddPackageProductRequest;
import com.lightboat.system.mapper.CrmProductMapper;
import com.lightboat.system.mapper.CrmProductStockRecordMapper;
import com.lightboat.system.service.ICrmProductService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 商品Service业务层处理
 *
 * @author lightboat
 * @date 2025-08-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CrmProductServiceImpl extends ServiceImpl<CrmProductMapper, CrmProduct> implements ICrmProductService {

    private final CrmProductMapper crmProductMapper;
    private final CrmProductStockRecordMapper crmProductStockRecordMapper;

    /**
     * 查询商品
     *
     * @param productId 商品主键
     * @return 商品
     */
    @Override
    public CrmProduct selectCrmProductByProductId(Long productId) {
        return crmProductMapper.selectCrmProductByProductId(productId);
    }

    /**
     * 查询商品列表
     *
     * @param crmProduct 商品
     * @return 商品
     */
    @Override
    public List<CrmProduct> selectCrmProductList(CrmProduct crmProduct) {
        return crmProductMapper.selectCrmProductList(crmProduct);
    }

    /**
     * 新增商品
     *
     * @param crmProduct 商品
     * @return 结果
     */
    @Override
    public int insertCrmProduct(CrmProduct crmProduct) {
        crmProduct.setCreateTime(DateUtils.getNowDate());
        return crmProductMapper.insert(crmProduct);
    }

    /**
     * 修改商品
     *
     * @param crmProduct 商品
     * @return 结果
     */
    @Override
    public int updateCrmProduct(CrmProduct crmProduct) {
        crmProduct.setUpdateTime(DateUtils.getNowDate());
        return crmProductMapper.updateById(crmProduct);
    }

    /**
     * 批量删除商品
     *
     * @param productIds 需要删除的商品主键
     * @return 结果
     */
    @Override
    public int deleteCrmProductByProductIds(Long[] productIds) {
        return crmProductMapper.deleteCrmProductByProductIds(productIds);
    }

    /**
     * 删除商品信息
     *
     * @param productId 商品主键
     * @return 结果
     */
    @Override
    public int deleteCrmProductByProductId(Long productId) {
        return crmProductMapper.deleteCrmProductByProductId(productId);
    }

    @Override
    public Map<String, Integer> syncCrmProduct(JSONArray json) {

        AtomicInteger count = new AtomicInteger();

        List<BaiDuJianKangApi.GoodsDetailResponse> goodsLists = json.toList(BaiDuJianKangApi.GoodsDetailResponse.class);
        goodsLists.forEach(item -> {
            CrmProduct crmProduct = new CrmProduct();
            crmProduct.setExternalProductId(item.getGoodsId().toString());
            crmProduct.setType(2);
            crmProduct.setExternalType(0);
            crmProduct.setProductCategory(item.getType());
            crmProduct.setProductSpec(item.getSpec());
            crmProduct.setExternalType(item.getGoodsType());
            crmProduct.setExternalPackageId(item.getGoodsType() == 1 ? item.getGoodsId().toString() : null);
            crmProduct.setStock(Convert.toLong(item.getSkuInfo().getStockSize()));
            crmProduct.setCostPrice(new BigDecimal(item.getSkuInfo().getPriceFen()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
            crmProduct.setSalePrice(new BigDecimal(Opt.ofNullable(item.getSkuInfo().getMarketPriceFen()).orElse(item.getSkuInfo().getPriceFen())).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
            crmProduct.setProductName(item.getCommonName());
            crmProduct.setProductTitle(item.getTitle());
            crmProduct.setProductImage(String.join(",", item.getPictures()));
            crmProduct.setProductUnitNum(Convert.toInt(RegexpUtils.extractBoxNumber(item.getSpec(), Constants.GOODS_UNITS[4])));
            crmProduct.setAttributeInfo(JSON.parseObject(JSON.toJSONString(item.getAttributeInfo())));
            Wrapper<CrmProduct> wrapper = Wrappers.<CrmProduct>lambdaQuery().eq(CrmProduct::getExternalProductId, item.getGoodsId());
            boolean b = crmProductMapper.update(crmProduct, wrapper) > 0 || crmProductMapper.insertOrUpdate(crmProduct);
            if (!b) {
                log.error("商品同步失败：{}", item.getGoodsId());
            }else {
                count.addAndGet(1);
            }
        });
        return Map.of("count", json.size(), "success", count.get());
    }

    @Override
    public int addPackage(AddPackageProductRequest request) {

        CrmProduct product = BeanUtil.copyProperties(request, CrmProduct.class);
        product.setType(ProductType.SELF.getType());
        product.setExternalType(1);

        return baseMapper.insert(product);
    }


    /**
     * 库存操作
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean stockOperation(CrmProductStockRecord stockRecord, OperationTypeEnum operationType) {
        return RedisUtils.builder().redissonLock(RedisConstants.STOCK_PREFIX + stockRecord.getProductId(), TimeUnit.SECONDS, 5, 10, () -> {
            switch (operationType){
                case ADD:
                    {
                        CrmProduct crmProduct = crmProductMapper.selectById(stockRecord.getProductId());
                        CrmProductStockRecord crmProductStockRecord = BeanUtil.copyProperties(stockRecord, CrmProductStockRecord.class);
                        crmProductStockRecord.setOperationType(1);
                        if (crmProduct != null) {
                            Long stock = crmProduct.getStock();
                            crmProductStockRecord.setOriginalStock(stock);
                            long remainingStock = stock + crmProductStockRecord.getChangeQuantity();
                            crmProductStockRecord.setRemainingStock(remainingStock);

                            CrmProduct updateProduct = new CrmProduct();
                            updateProduct.setProductId(crmProduct.getProductId());
                            updateProduct.setStock(remainingStock);
                            crmProductMapper.updateById(updateProduct);
                        }
                        crmProductStockRecordMapper.insert(crmProductStockRecord);
                    }
                    break;
                case REDUCE:
                    {
                        CrmProduct crmProduct = crmProductMapper.selectById(stockRecord.getProductId());
                        CrmProductStockRecord crmProductStockRecord = BeanUtil.copyProperties(stockRecord, CrmProductStockRecord.class);
                        crmProductStockRecord.setOperationType(2);
                        if (crmProduct != null) {
                            Long stock = crmProduct.getStock();
                            crmProductStockRecord.setOriginalStock(stock);
                            long remainingStock = stock - crmProductStockRecord.getChangeQuantity();
                            if (remainingStock < 0) {
                                throw new ServiceException(StrUtil.format("商品:{}，库存不足，剩余库存：{}", crmProduct.getProductName(), stock));
                            }
                            crmProductStockRecord.setRemainingStock(remainingStock);

                            CrmProduct updateProduct = new CrmProduct();
                            updateProduct.setProductId(crmProduct.getProductId());
                            updateProduct.setStock(remainingStock);
                            crmProductMapper.updateById(updateProduct);
                        }
                        crmProductStockRecordMapper.insert(crmProductStockRecord);
                    }
                    break;
                default:
                    throw new RuntimeException("商品库存操作失败");
            }
            return true;
        }, "商品库存操作失败");
    }
}
